﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.Server;
using Microsoft.VisualStudio.TeamFoundation;

namespace WorkItemCollaborator
{
    internal delegate void ProjectUsersLoadedHandler(string projectName);
    internal class WicUserStore
    {

        Dictionary<string, Collection<User>> projectUsers = new Dictionary<string, Collection<User>>();
        private readonly object projectUsersListLock = new object();
        private bool loadingProjectUsers = false;
        private delegate void UserLoadCaller(ProjectContext projectContext);

        internal event ProjectUsersLoadedHandler ProjectUsersLoaded;
        public void ProcessProjectUsers(ProjectContext projectContext)
        {
            if (projectContext != null && !String.IsNullOrEmpty(projectContext.ProjectName) && !projectUsers.ContainsKey(projectContext.ProjectName))
            {
                bool alreadyLoadingUsers = false;
                lock (projectUsersListLock)
                {
                    alreadyLoadingUsers = loadingProjectUsers;
                }
                if (!alreadyLoadingUsers)
                {
                    LoadProjectUsersAsync(projectContext);
                }
            }
        }

        public Collection<User> GetProjectUsersCollection(ProjectContext projectContext)
        {
            Collection<User> projectUsersCollection = null;
            lock (projectUsersListLock)
            {
                if (projectUsers.ContainsKey(projectContext.ProjectName))
                {
                    projectUsersCollection = projectUsers[projectContext.ProjectName];
                }
            }
            return projectUsersCollection;
        }

        private void LoadProjectUsersAsync(ProjectContext projectContext)
        {   
            if (projectContext != null && !String.IsNullOrEmpty(projectContext.ProjectName))
            {
                var userLoadDelegate = new UserLoadCaller(LoadSelectedProjectsUserDetails);
                userLoadDelegate.BeginInvoke(projectContext, null, null);
            }
        }

        private void LoadSelectedProjectsUserDetails(ProjectContext projectContext)
        {
            try
            {
                lock (projectUsersListLock)
                {
                    loadingProjectUsers = true;
                }

                Collection<User> users = new Collection<User>();
                TfsTeamProjectCollection tpc = TfsTeamProjectCollectionFactory.GetTeamProjectCollection(
                    new Uri(projectContext.DomainUri));
                if (tpc != null)
                {
                    IGroupSecurityService groupSecurityServices = tpc.GetService<IGroupSecurityService>();

                    Identity[] allProjectGroups = groupSecurityServices.ListApplicationGroups(projectContext.ProjectName);
                    if (allProjectGroups != null && allProjectGroups.Length > 0)
                    {
                        Identity contributors = allProjectGroups.FirstOrDefault(row => row.AccountName == "Contributors");
                        if (contributors != null)
                        {
                            Identity projectGroupIdentity = groupSecurityServices.ReadIdentity(SearchFactor.Sid,
                                                                                           contributors.Sid,
                                                                                           QueryMembership.Expanded);

                            Identity[] identities = groupSecurityServices.ReadIdentities(SearchFactor.Sid, projectGroupIdentity.Members,
                                                                                QueryMembership.None);
                            foreach (var identity in identities)
                            {
                                users.Add(new User(identity.DisplayName, identity.MailAddress));
                            }
                        }
                    }
                    
                    lock (projectUsersListLock)
                    {
                        projectUsers.Add(projectContext.ProjectName, users);
                    }

                    if(ProjectUsersLoaded != null)
                    {
                        ProjectUsersLoaded(projectContext.ProjectName);
                    }
                }
            }
            finally
            {
                lock (projectUsersListLock)
                {
                    loadingProjectUsers = false;
                }
            }
        }

    }
}
